﻿using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI;
using Microsoft.Graphics.Canvas.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.System;
using Windows.UI;
using Windows.UI.Text;
using Windows.UI.Text.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Documents;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;

using FocusStatus = System.Boolean;

// The Templated Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234235

namespace InspirationNote.Core
{
    public sealed class MarkdownEditorControl : UserControl
    {
        #region Constuctor & Loaded UnLoaded Event 

        public MarkdownEditorControl()
        {
            this.Loaded += OnLoaded;
            this.Unloaded += OnUnloaded;
            this.InitializeTextService();            
        }

        private void OnUnloaded(object sender, RoutedEventArgs e)
        {
            if (_canvas != null) {
                _canvas.RemoveFromVisualTree();
                _canvas = null;
            }
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            _canvas = new CanvasControl();
            _canvas.Draw += Canvas_Draw;
            _canvas.CreateResources += Canvas_CreateResources;
            this.Content = _canvas;
        }

        #endregion

        // Text Service

        CoreTextEditContext     _context;
        InputPane               _inputPane;

        // Text Format 
        CanvasControl           _canvas;
        ICanvasBrush            _textFormatBrush;
        ICanvasBrush            _caretBrush;
        CanvasTextFormat        _format;

        // Text Content
        string                  _content;
        FocusStatus             _isFocus;

        #region Text Service

        void InitializeTextService()
        {
            var manager = CoreTextServicesManager.GetForCurrentView();
            _inputPane = InputPane.GetForCurrentView();
            manager.InputLanguageChanged += OnInputLanguageChanged;

            _context = manager.CreateEditContext();
            _context.InputScope = CoreTextInputScope.Text;
            _context.InputPaneDisplayPolicy = CoreTextInputPaneDisplayPolicy.Manual;

            Debug.Assert(_context != null);

            // 当合成完成时
            _context.CompositionCompleted += OnCompositionCompleted;

            //当开始合成时
            _context.CompositionStarted += OnCompositionStarted;

            //当焦点移除时
            _context.FocusRemoved += OnFocusRemoved;

            //当文本格式变化时
            _context.FormatUpdating += OnFormatUpdating;

            //当请求布局时
            _context.LayoutRequested += OnLayoutRequested;

            //当通知焦点离开完成时
            _context.NotifyFocusLeaveCompleted += OnNotifyFocusLeaveCompleted;

            //当请求选择时
            _context.SelectionRequested += OnSelectionRequested;

            //当选择更新时
            _context.SelectionUpdating += OnSelectionUpdating;

            //当文本请求时
            _context.TextRequested += OnTextRequested;

            // 当文本更新时
            _context.TextUpdating += OnTextUpdating;
        }

        private void OnTextUpdating(CoreTextEditContext sender, CoreTextTextUpdatingEventArgs args)
        {
            _content += args.Text;
        }

        private void OnTextRequested(CoreTextEditContext sender, CoreTextTextRequestedEventArgs args)
        {

        }

        private void OnSelectionUpdating(CoreTextEditContext sender, CoreTextSelectionUpdatingEventArgs args)
        {

        }

        private void OnSelectionRequested(CoreTextEditContext sender, CoreTextSelectionRequestedEventArgs args)
        {

        }

        private void OnNotifyFocusLeaveCompleted(CoreTextEditContext sender, object args)
        {

        }

        private void OnLayoutRequested(CoreTextEditContext sender, CoreTextLayoutRequestedEventArgs args)
        {
            _canvas.Invalidate();
        }

        private void OnFormatUpdating(CoreTextEditContext sender, CoreTextFormatUpdatingEventArgs args)
        {

        }

        private void OnFocusRemoved(CoreTextEditContext sender, object args)
        {

        }

        private void OnCompositionStarted(CoreTextEditContext sender, CoreTextCompositionStartedEventArgs args)
        {
            // 暂时不实现
        }

        private void OnCompositionCompleted(CoreTextEditContext sender, CoreTextCompositionCompletedEventArgs args)
        {
            // 暂时不实现
        }

        private void OnInputLanguageChanged(CoreTextServicesManager sender, object args)
        {
            //当输入的语言变化时
        }



        #endregion

        #region Key Service

        protected override void OnKeyDown(KeyRoutedEventArgs e)
        {
            switch (e.Key) {
                case VirtualKey.Left:
                case VirtualKey.Up:
                case VirtualKey.Down:
                case VirtualKey.Right:
                case VirtualKey.PageUp:
                case VirtualKey.PageDown:
                case VirtualKey.Shift:
                    break;
            }
            base.OnKeyDown(e);
        }

        protected override void OnKeyUp(KeyRoutedEventArgs e)
        {
            switch (e.Key) {
                case VirtualKey.Left:
                case VirtualKey.Up:
                case VirtualKey.Down:
                case VirtualKey.Right:
                case VirtualKey.PageUp:
                case VirtualKey.PageDown:
                case VirtualKey.Shift:
                    break;
            }
            base.OnKeyUp(e);
        }

        #endregion

        #region Focus Managed   

        protected override void OnGotFocus(RoutedEventArgs e)
        {

            base.OnGotFocus(e);
        }

        protected override void OnLostFocus(RoutedEventArgs e)
        {
            if (_isFocus) {
                _isFocus = false;
                _context.NotifyFocusLeave();
                _inputPane.TryHide();                
            }

            base.OnLostFocus(e);
        }

        #endregion

        #region Pointer Service

        protected override void OnPointerPressed(PointerRoutedEventArgs e)
        {
            if (!_isFocus) {                
                _isFocus = true;
                this.Focus(FocusState.Programmatic);
                _context.NotifyFocusEnter();
                _inputPane.TryShow();
            }
            base.OnPointerPressed(e);
        }

        protected override void OnPointerReleased(PointerRoutedEventArgs e)
        {
            base.OnPointerReleased(e);
        }

        #endregion

        #region Text Property

        /// <summary>
        /// 获取或设置当前空间的默认字体颜色
        /// </summary>
        public Brush TextForeground {
            get { return (Brush)GetValue(TextForegroundProperty); }
            set { SetValue(TextForegroundProperty, value); }
        }

        public static readonly DependencyProperty TextForegroundProperty =
        DependencyProperty.Register("TextForeground", typeof(Brush), typeof(MarkdownEditorControl), new PropertyMetadata(null,TextForegroundChangedCallback));

        static void TextForegroundChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue == null) {
                return;
            }

            var editor = obj as MarkdownEditorControl;
            var brush = e.NewValue as Brush;
            CreateSolidColorBrush(editor, brush);
            CreateLinearGradientBrush(editor, brush);
        }

        static void CreateSolidColorBrush(MarkdownEditorControl editor, Brush brush)
        {
            if (brush is SolidColorBrush scb) {
                // TODO error:
                // 
                // editor._textFormatBrush = new CanvasSolidColorBrush(editor.Canvas, scb.Color);
            }
        }

        static void CreateLinearGradientBrush(MarkdownEditorControl editor, Brush brush)
        {
            if (brush is LinearGradientBrush lgb) {

            }
        }



        void SetTextFormat(ICanvasTextInlineObject customTrimmingSign, CanvasTextDirection direction, string fontFamily,
            float fontSize, FontStretch stretch, FontStyle style, FontWeight weight, CanvasHorizontalAlignment horizontal,
            float tabstop, bool lastLineWrapping, float lineSpacing, float lineSpacingBaseLine, CanvasLineSpacingMode spacingMode, string locateName,
            CanvasOpticalAlignment opticalAlignment, CanvasDrawTextOptions drawTextOptions, string trimmingDelimiter, int trimmingDelimiterCount,
            CanvasTextTrimmingGranularity trimmingGranularity, CanvasTrimmingSign trimmingSign, CanvasVerticalAlignment verticalAlignment,
            CanvasVerticalGlyphOrientation glyphOrientation, CanvasWordWrapping wordWrapping)
        {
            _format = new CanvasTextFormat
            {
                CustomTrimmingSign = customTrimmingSign,
                Direction = direction,
                FontFamily = fontFamily,
                FontSize = fontSize,
                FontStretch = stretch,
                FontStyle = style,
                FontWeight = weight,
                HorizontalAlignment = horizontal,
                IncrementalTabStop = tabstop,
                LastLineWrapping = lastLineWrapping,
                LineSpacing = lineSpacing,
                LineSpacingBaseline = lineSpacingBaseLine,
                LineSpacingMode = spacingMode,
                LocaleName = locateName,
                OpticalAlignment = opticalAlignment,
                Options = drawTextOptions,
                TrimmingDelimiter = trimmingDelimiter,
                TrimmingDelimiterCount = trimmingDelimiterCount,
                TrimmingGranularity = trimmingGranularity,
                TrimmingSign = trimmingSign,
                VerticalAlignment = verticalAlignment,
                VerticalGlyphOrientation = glyphOrientation,
                WordWrapping = wordWrapping
            };
        }

        #endregion

        #region Layout

        void LayoutCaret(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
        {
            var showcaret = DateTime.Now.Second % 2 == 0;
            if (showcaret) {
                args.DrawingSession.DrawRectangle(new Rect(0, 0, 1, 32), _caretBrush);
            }
        }

        void LayoutCaret(CanvasControl sender, CanvasDrawEventArgs args)
        {
            var showcaret = DateTime.Now.Second % 2 == 0;
            if (showcaret) {
                args.DrawingSession.DrawRectangle(new Rect(0, 0, 1, 32), _caretBrush);
            }
        }

        void LayoutText(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
        {
            if (!string.IsNullOrEmpty(_content)) {
                var session = args.DrawingSession;
                session.DrawText(_content, new Vector2(0, 0), Colors.Black);
            }
        }

        void LayoutText(CanvasControl sender, CanvasDrawEventArgs args)
        {
            if (!string.IsNullOrEmpty(_content)) {
                var session = args.DrawingSession;
                session.DrawText(_content, new Vector2(0, 0), Colors.Black);
            }
        }

        #endregion

        //// CanvasAnimatedControl
        //private void Canvas_Draw(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
        //{
        //    LayoutText(sender, args);
        //    LayoutCaret(sender, args);
        //}

        //private void Canvas_CreateResources(CanvasAnimatedControl sender, CanvasCreateResourcesEventArgs args)
        //{
        //    _caretBrush = new CanvasSolidColorBrush(sender, Colors.Black);
        //}

        // CanvasControl
        private void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args)
        {
            LayoutText(sender, args);
            LayoutCaret(sender, args);
        }

        private void Canvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args)
        {
            _caretBrush = new CanvasSolidColorBrush(sender, Colors.Black);
        }
    }
}
